﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace MPEGnet
{
    public class ThreadedDispatch
    {
        int _numBackgroundThreads;

        public ThreadedDispatch(int numBackgroundThreads)
        {
            _numBackgroundThreads = numBackgroundThreads;
        }

        public void Dispatch(int startInclusive, int endExclusive, Action<int> action)
        {
            int index = 0;
            int numActiveThreads = 0;

            WaitCallback proc = delegate(object state)
            {
                System.Threading.Interlocked.Increment(ref numActiveThreads);
                while (true)
                {
                    int procIndex = System.Threading.Interlocked.Increment(ref index) - 1;
                    if (procIndex >= endExclusive)
                    {
                        System.Threading.Interlocked.Decrement(ref numActiveThreads);
                        return;
                    }

                    try
                    {
                        action(procIndex);
                    }
                    catch
                    {
                        System.Threading.Interlocked.Decrement(ref numActiveThreads);
                        throw;
                    }
                }
            };

            for (int i = 0; i < _numBackgroundThreads; i++)
                ThreadPool.QueueUserWorkItem(proc);

            proc(null);
            while (numActiveThreads != 0)
            {
                Thread.MemoryBarrier();
            }
        }
    }
}
